/*
     Copyright 2007 Joseph M. Ferner

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/

using OpenServers.Net.FtpServer.State;

namespace OpenServers.Net.FtpServer.Command {
    /// <summary>
    ///     <para>
    ///         <b>REPRESENTATION TYPE (TYPE)</b><br/>
    ///         The argument specifies the representation type as described
    ///         in the Section on Data Representation and Storage.  Several
    ///         types take a second parameter.  The first parameter is
    ///         denoted by a single Telnet character, as is the second
    ///         Format parameter for ASCII and EBCDIC; the second parameter
    ///         for local byte is a decimal integer to indicate Bytesize.
    ///         The parameters are separated by a &lt;SP&gt; (Space, ASCII code 32).
    ///     </para>
    ///     <para>
    ///         The default representation type is ASCII Non-print.  If the
    ///         Format parameter is changed, and later just the first
    ///         argument is changed, Format then returns to the Non-print
    ///         default.
    ///     </para>
    ///     <para>
    ///         <b>Types:</b>
    ///         <list type="bullet">
    ///             <item><term>A</term><description>ASCII - Subtype: N, T, C</description></item>
    ///             <item><term>E</term><description>EBCDIC - Subtype: N, T, C</description></item>
    ///             <item><term>I</term><description>Image - Subtype: None</description></item>
    ///             <item><term>L</term><description>Local byte size - Subtype: &lt;byte size&gt;</description></item>
    ///         </list>
    ///     </para>
    ///     <para>
    ///         <b>Subtypes:</b>
    ///         <list type="bullet">
    ///             <item><term>N</term><description>Non-print</description></item>
    ///             <item><term>T</term><description>Telnet format effectors</description></item>
    ///             <item><term>C</term><description>Carriage Control (ASA)</description></item>
    ///         </list>
    ///     </para>
    ///     <para>
    ///         <b>Format</b><br/>
    ///         <code>
    /// TYPE &lt;SP&gt; &lt;type-code&gt; &lt;CRLF&gt;<br/>
    /// &lt;type-code&gt; ::= A [&lt;sp&gt; &lt;form-code&gt;]<br/>
    ///               | E [&lt;sp&gt; &lt;form-code&gt;]<br/>
    ///               | I<br/>
    ///               | L &lt;sp&gt; &lt;byte-size&gt;<br/>
    /// &lt;byte-size&gt; ::= &lt;number&gt;<br/>
    /// &lt;form-code&gt; ::= N | T | C</code>
    ///     </para>
    ///     <para>
    ///         <b>Success:</b>
    ///         <list type="bullet">
    ///             <item><term>250</term><description>Requested file action okay, completed.</description></item>
    ///         </list>
    ///     </para>
    ///     <para>
    ///         <b>Errors:</b>
    ///         <list type="bullet">
    ///             <item><term>500</term><description>Syntax error, command unrecognized.</description></item>
    ///             <item><term>501</term><description>Syntax error in parameters or arguments.</description></item>
    ///             <item><term>502</term><description>Command not implemented.</description></item>
    ///             <item><term>421</term><description>Service not available, closing control connection.</description></item>
    ///             <item><term>530</term><description>Not logged in.</description></item>
    ///             <item><term>550</term><description>Requested action not taken. File unavailable (e.g., file not found, no access).</description></item>
    ///         </list>
    ///     </para>
    /// </summary>
    public class TypeCommand : BaseCommand {
        /// <summary>
        /// Sets the current type.
        /// </summary>
        public override void PerformCommand(IFtpServer server, FtpState state, string arguments) {
            if (string.IsNullOrEmpty(arguments)) {
                state.Listener.Send(state, server.Messages.Get501());
            } else {
                string[] argumentParts = arguments.Split(' ');
                if (argumentParts[0] == "A" || argumentParts[0] == "E") {
                    FtpState.Type.TypeEnum type;
                    if (argumentParts[0] == "A") {
                        type = FtpState.Type.TypeEnum.Ascii;
                    } else {
                        type = FtpState.Type.TypeEnum.Ebcdic;
                    }

                    if (argumentParts.Length == 1) {
                        state.CurrentType.CurrentType = type;
                        state.Listener.Send(state, server.Messages.Get200());
                    } else if (argumentParts.Length == 2) {
                        if (argumentParts[1] == "N") {
                            state.CurrentType.CurrentType = type;
                            state.CurrentType.SubType = FtpState.Type.SubTypeEnum.NonPrint;
                            state.Listener.Send(state, server.Messages.Get200());
                        } else if (argumentParts[1] == "T") {
                            state.CurrentType.CurrentType = type;
                            state.CurrentType.SubType = FtpState.Type.SubTypeEnum.TelnetFormEffectors;
                            state.Listener.Send(state, server.Messages.Get200());
                        } else if (argumentParts[1] == "C") {
                            state.CurrentType.CurrentType = type;
                            state.CurrentType.SubType = FtpState.Type.SubTypeEnum.CarriageControl;
                            state.Listener.Send(state, server.Messages.Get200());
                        } else {
                            state.Listener.Send(state, server.Messages.Get501());
                        }
                    } else {
                        state.Listener.Send(state, server.Messages.Get501());
                    }
                } else if (argumentParts[0] == "I") {
                    if (argumentParts.Length != 1) {
                        state.Listener.Send(state, server.Messages.Get501());
                    } else {
                        state.CurrentType.CurrentType = FtpState.Type.TypeEnum.Image;
                        state.Listener.Send(state, server.Messages.Get200());
                    }
                } else if (argumentParts[0] == "L") {
                    if (argumentParts.Length != 2) {
                        state.Listener.Send(state, server.Messages.Get501());
                    } else {
                        int localByteSize;
                        if (int.TryParse(argumentParts[1], out localByteSize)) {
                            state.CurrentType.CurrentType = FtpState.Type.TypeEnum.LocalByteSize;
                            state.CurrentType.LocalByteSize = localByteSize;
                            state.Listener.Send(state, server.Messages.Get200());
                        } else {
                            state.Listener.Send(state, server.Messages.Get501());
                        }
                    }
                } else {
                    state.Listener.Send(state, server.Messages.Get501());
                }
            }
        }
    }
}
